import pygame
import logging
from typing import Optional
from ..theme import Theme
from ..word_bank import WordBank

class PracticeView:
    def __init__(self, screen: pygame.Surface, theme: Theme, word_bank: WordBank):
        self.screen = screen
        self.theme = theme
        self.word_bank = word_bank
        self.current_words = []
        self.current_word_index = 0
        self.current_input = ""
        
        # 添加单词数量选择（移到前面）
        self.word_count_options = [5, 10, 20, 50]
        self.current_word_count = 10  # 默认10个单词
        
        self.typing_stats = {
            "correct_words": 0,
            "wrong_words": 0,
            "total_chars": 0,
            "start_time": None,
            "current_wpm": 0,
            "current_accuracy": 0
        }
        self.show_wpm = False
        self.show_import_dialog = False
        self.show_export_dialog = False
        
        # 移到所有属性初始化之后
        self.load_words()
        
        self.cursor_visible = True
        self.cursor_blink_time = 500  # 光标闪烁间隔(毫秒)
        self.last_blink_time = pygame.time.get_ticks()
        self.show_word_info = False  # 添加标志来控制是否显示单词信息
        self.input_correct = None    # 添加标志来标记输入是否正确
        
    def load_words(self) -> None:
        """加载练习单词"""
        # 获取当前选择的词库
        current_bank = self.word_bank.current_bank
        logging.info(f"正在加载词库: {current_bank}")
        
        # 尝试加载当前选择的词库
        if not self.word_bank.load_word_bank(current_bank):
            logging.warning(f"加载词库 {current_bank} 失败，尝试加载默认词库")
            # 如果失败，尝试加载默认词库
            if not self.word_bank.load_word_bank("default"):
                logging.warning("加载默认词库失败，创建新的默认词库")
                # 如果默认词库也不存在，创建一个
                self.word_bank.create_default_word_bank()
                self.word_bank.load_word_bank("default")
        
        # 获取词库信息
        bank_info = self.word_bank.get_bank_info()
        logging.info(f"当前词库: {bank_info.get('name', current_bank)}")
        logging.info(f"词库大小: {len(self.word_bank.words)} 个单词")
        
        # 获取练习单词
        self.current_words = self.word_bank.get_words(self.current_word_count)
        if not self.current_words:
            logging.error("无法获取练习单词")
        else:
            logging.info(f"已获取 {len(self.current_words)} 个练习单词")
        
    def handle_event(self, event: pygame.event.Event) -> Optional[str]:
        """处理事件"""
        if event.type == pygame.KEYDOWN:
            if event.key == pygame.K_ESCAPE:
                return "menu"
                
            if self.show_word_info:
                if event.key == pygame.K_r and not self.input_correct:
                    # 按R重试当前单词
                    self.show_word_info = False
                    self.current_input = ""
                elif event.key == pygame.K_RETURN:
                    # 按回车继续下一个
                    self.show_word_info = False
                    self.current_word_index += 1
                    self.current_input = ""
                    
                    if self.current_word_index >= len(self.current_words):
                        self.show_typing_stats()
                        self.current_word_index = 0
                        self.current_words = self.word_bank.get_words(self.current_word_count)
            else:
                if event.key == pygame.K_RETURN:
                    self.check_input()
                elif event.key == pygame.K_BACKSPACE:
                    self.current_input = self.current_input[:-1]
                elif event.key == pygame.K_i and pygame.key.get_mods() & pygame.KMOD_CTRL:
                    self._show_import_dialog()
                elif event.key == pygame.K_e and pygame.key.get_mods() & pygame.KMOD_CTRL:
                    self._show_export_dialog()
                elif event.unicode and event.unicode.isprintable():
                    self.current_input += event.unicode
                    
                return None
                    
        elif event.type == pygame.MOUSEBUTTONDOWN and event.button == 1:  # 左键点击
            # 检查是否点击了单词数量选项
            mouse_pos = pygame.mouse.get_pos()
            left_panel_rect = pygame.Rect(0, 0, self.screen.get_width() * 0.2, self.screen.get_height())
            
            if left_panel_rect.collidepoint(mouse_pos):
                # 计算选项的位置
                for i, count in enumerate(self.word_count_options):
                    option_rect = pygame.Rect(
                        left_panel_rect.left + 10 + (i * 50),
                        95,
                        40, 25
                    )
                    if option_rect.collidepoint(mouse_pos):
                        if self.current_word_count != count:
                            self.current_word_count = count
                            # 重新加载单词
                            self.current_word_index = 0
                            self.current_input = ""
                            self.show_word_info = False
                            self.current_words = self.word_bank.get_words(self.current_word_count)
                    return None
                
    def check_input(self) -> None:
        """检查用户输入"""
        if not self.current_words:
            return
            
        if self.typing_stats["start_time"] is None:
            self.typing_stats["start_time"] = pygame.time.get_ticks()
        
        current_word = self.current_words[self.current_word_index]
        word_text = current_word['word'] if isinstance(current_word, dict) else str(current_word)
        
        # 检查用户输入
        if self.current_input == word_text:
            self.typing_stats["correct_words"] += 1
            self.typing_stats["total_chars"] += len(word_text)
            self.input_correct = True
        else:
            self.typing_stats["wrong_words"] += 1
            self.input_correct = False
            
        self._update_typing_stats()
        self.show_word_info = True  # 显示单词信息
        
    def _update_typing_stats(self) -> None:
        """更新打字统计信息"""
        if self.typing_stats["start_time"] is None:
            return
        
        elapsed_time = (pygame.time.get_ticks() - self.typing_stats["start_time"]) / 1000  # 转换为秒
        if elapsed_time > 0:
            # 计算 WPM
            self.typing_stats["current_wpm"] = (self.typing_stats["total_chars"] / 5) / (elapsed_time / 60)
            
            # 计算准确率
            total_words = self.typing_stats["correct_words"] + self.typing_stats["wrong_words"]
            self.typing_stats["current_accuracy"] = (self.typing_stats["correct_words"] / max(1, total_words)) * 100

    def show_typing_stats(self) -> None:
        """显示打字统计信息"""
        if self.typing_stats["start_time"] is None:
            return
        
        self._update_typing_stats()
        self.show_wpm = True
        logging.info(
            f"WPM: {self.typing_stats['current_wpm']:.1f}, "
            f"准确率: {self.typing_stats['current_accuracy']:.1f}%"
        )
        
    def draw(self) -> None:
        """绘制视图"""
        self.screen.fill(self.theme.background_color)
        
        if not self.current_words:
            self._draw_error_message()
            return
        
        # 将屏幕分为三个区域
        left_panel = pygame.Rect(0, 0, self.screen.get_width() * 0.2, self.screen.get_height())  # 左侧20%
        center_panel = pygame.Rect(left_panel.right, 0, self.screen.get_width() * 0.6, self.screen.get_height())  # 中间60%
        right_panel = pygame.Rect(center_panel.right, 0, self.screen.get_width() * 0.2, self.screen.get_height())  # 右侧20%
        
        # 绘制三个区域的分隔线
        pygame.draw.line(self.screen, self.theme.border_color, (left_panel.right, 0), (left_panel.right, self.screen.get_height()), 1)
        pygame.draw.line(self.screen, self.theme.border_color, (right_panel.left, 0), (right_panel.left, self.screen.get_height()), 1)
        
        # 绘制左侧面板（功能提示区）
        self._draw_left_panel(left_panel)
        
        # 绘制中间面板（练习区）
        self._draw_center_panel(center_panel)
        
        # 绘制右侧面板（统计区）
        self._draw_right_panel(right_panel)

    def _draw_left_panel(self, rect: pygame.Rect) -> None:
        """绘制左侧面板（功能提示区）"""
        # 绘制标题
        self.theme.draw_text(self.screen, "功能提示", (rect.centerx, 30), center=True, size=24)
        
        # 绘制单词数量选择
        count_text = "练习数量: "
        self.theme.draw_text(self.screen, count_text, (rect.left + 10, 70), size=20)
        
        # 绘制选项
        for i, count in enumerate(self.word_count_options):
            x = rect.left + 10 + (i * 50)  # 水平排列选项
            y = 95
            # 创建选项的矩形区域
            option_rect = pygame.Rect(x, y, 40, 25)
            
            # 绘制选项背景
            if count == self.current_word_count:
                # 选中状态
                pygame.draw.rect(self.screen, self.theme.highlight_color, option_rect)
                text_color = self.theme.background_color
            else:
                # 未选中状态
                pygame.draw.rect(self.screen, self.theme.border_color, option_rect, 1)
                text_color = self.theme.text_color
            
            # 绘制选项文本
            self.theme.draw_text(self.screen, str(count), 
                               (option_rect.centerx, option_rect.centery),
                               center=True, size=16, color=text_color)
        
        # 绘制进度条（位置下移）
        progress_text = f"进度: {self.current_word_index + 1}/{len(self.current_words)}"
        self.theme.draw_text(self.screen, progress_text, (rect.left + 10, 130), size=20)
        
        progress_rect = pygame.Rect(rect.left + 10, 160, rect.width - 20, 10)
        pygame.draw.rect(self.screen, self.theme.border_color, progress_rect, 1)
        progress = self.current_word_index / len(self.current_words)
        fill_rect = pygame.Rect(progress_rect.left + 1, progress_rect.top + 1, 
                              (progress_rect.width - 2) * progress, progress_rect.height - 2)
        pygame.draw.rect(self.screen, self.theme.progress_bar_color, fill_rect)
        
        # 绘制操作提示
        hints = [
            "ESC - 返回菜单",
            "Enter - 提交答案",
            "Backspace - 删除",
            "Ctrl+I - 导入词库",
            "Ctrl+E - 导出词库"
        ]
        
        # 如果正在显示结果，替换提交答案的提示
        if self.show_word_info:
            hints[1] = "Enter - 下一个单词"  # 替换原来的"Enter - 提交答案"
            if not self.input_correct:
                hints.insert(1, "R - 重试本词")  # 在Enter提示前插入重试提示
        
        # 绘制提示文本
        for i, hint in enumerate(hints):
            y_pos = rect.bottom - (len(hints) * 30 + 20) + i * 30
            self.theme.draw_text(self.screen, hint, (rect.left + 10, y_pos), size=20)

    def _draw_center_panel(self, rect: pygame.Rect) -> None:
        """绘制中间面板（练习区）"""
        # 绘制标题
        bank_info = self.word_bank.get_bank_info()
        bank_name = bank_info.get('name', self.word_bank.current_bank)
        title = f"练习模式 - {bank_name}"
        self.theme.draw_text(self.screen, title, (rect.centerx, 30), center=True, size=36)
        
        # 上半部分：单词显示和输入
        word_area = pygame.Rect(rect.left + 20, 100, rect.width - 40, rect.height // 2 - 100)
        
        if self.current_word_index < len(self.current_words):
            word_obj = self.current_words[self.current_word_index]
            word_text = word_obj['word'] if isinstance(word_obj, dict) else str(word_obj)
            
            # 绘制单词
            self.theme.draw_text(self.screen, word_text, (word_area.centerx, word_area.centery - 40), 
                               center=True, size=48)
            
            # 绘制输入框或结果
            if self.show_word_info:
                # 显示输入结果
                y = word_area.centery + 40
                baseline_y = y  # 使用固定的基准线位置
                
                if self.input_correct:
                    # 如果完全正确，显示绿色
                    text_surface = self.theme.render_text(self.current_input, size=48, color=self.theme.correct_color)
                    text_rect = text_surface.get_rect()
                    text_rect.bottom = baseline_y  # 直接使用基准线作为底部位置
                    text_rect.centerx = word_area.centerx
                    self.screen.blit(text_surface, text_rect)
                else:
                    # 如果有错误，逐字符显示并标记错误
                    # 先计算所有字符的宽度和间距
                    char_spacing = 10  # 字符间距
                    char_surfaces = []
                    total_width = 0
                    
                    # 预渲染所有字符
                    for i, char in enumerate(self.current_input):
                        if i < len(word_text) and char == word_text[i]:
                            color = self.theme.text_color
                        else:
                            color = self.theme.wrong_color
                        char_surface = self.theme.render_text(char, size=48, color=color)
                        char_surfaces.append(char_surface)
                        total_width += char_surface.get_width()
                    
                    # 添加字符间距到总宽度
                    total_width += char_spacing * (len(self.current_input) - 1)
                    
                    # 计算起始位置，使文本居中
                    start_x = word_area.centerx - total_width // 2
                    x = start_x
                    
                    # 绘制每个字符，底部对齐
                    for char_surface in char_surfaces:
                        char_rect = char_surface.get_rect()
                        char_rect.bottom = baseline_y  # 直接使用基准线作为底部位置
                        char_rect.left = x
                        self.screen.blit(char_surface, char_rect)
                        x += char_surface.get_width() + char_spacing
            else:
                # 绘制输入框
                input_rect = pygame.Rect(word_area.centerx - 200, word_area.centery + 40, 400, 60)
                pygame.draw.rect(self.screen, self.theme.border_color, input_rect, 2)
                pygame.draw.rect(self.screen, (*self.theme.background_color, 230), input_rect)  # 添加半透明背景
                
                # 绘制用户输入
                if self.current_input:
                    self.theme.draw_text(self.screen, self.current_input, 
                                       (input_rect.centerx, input_rect.centery),
                                       center=True, size=48, color=self.theme.input_color)
                
                # 绘制光标
                if self.cursor_visible:
                    text_width = self.theme.render_text(self.current_input, size=48).get_width()
                    cursor_x = input_rect.centerx + text_width // 2
                    pygame.draw.line(self.screen, self.theme.input_color,
                                   (cursor_x, input_rect.centery - 20),
                                   (cursor_x, input_rect.centery + 20), 2)
        
        # 下半部分：词性和释义
        if self.show_word_info and isinstance(word_obj, dict):
            info_area = pygame.Rect(rect.left + 20, rect.height // 2 + 50, 
                                  rect.width - 40, rect.height // 2 - 100)
            
            pos = word_obj.get('pos', '')
            meaning = word_obj.get('meaning', '') or word_obj.get('definition', '')
            if pos or meaning:
                info_text = f"{pos} {meaning}".strip()
                # 使用自动换行的文本渲染
                self._draw_wrapped_text(info_text, info_area, size=28)

    def _draw_right_panel(self, rect: pygame.Rect) -> None:
        """绘制右侧面板（统计区）"""
        # 绘制标题
        self.theme.draw_text(self.screen, "统计信息", (rect.centerx, 30), center=True, size=24)
        
        # 绘制打字统计
        if self.typing_stats["start_time"] is not None:
            stats = [
                f"WPM: {self.typing_stats['current_wpm']:.1f}",
                f"准确率: {self.typing_stats['current_accuracy']:.1f}%",
                f"正确: {self.typing_stats['correct_words']}",
                f"错误: {self.typing_stats['wrong_words']}"
            ]
            
            for i, stat in enumerate(stats):
                self.theme.draw_text(self.screen, stat, (rect.left + 10, 70 + i * 30), size=20)
        
        # 绘制分隔线
        pygame.draw.line(self.screen, self.theme.border_color, 
                        (rect.left + 10, 200), 
                        (rect.right - 10, 200), 1)
        
        # 绘制测试记录标题
        self.theme.draw_text(self.screen, "测试记录", (rect.centerx, 230), center=True, size=24)
        
        # 记录测试结果
        if self.show_word_info and self.current_word_index < len(self.current_words):
            word_obj = self.current_words[self.current_word_index]
            word_text = word_obj['word'] if isinstance(word_obj, dict) else str(word_obj)
            
            # 获取词性和释义
            pos = ""
            meaning = ""
            if isinstance(word_obj, dict):
                pos = word_obj.get('pos', '')
                meaning = word_obj.get('meaning', '') or word_obj.get('definition', '')
            
            # 创建记录文本
            record_text = f"{word_text}"
            if self.input_correct:
                status = "正确"  # 修改为中文
                record_color = self.theme.correct_color
            else:
                status = f"错误: {self.current_input}"  # 修改为中文
                record_color = self.theme.wrong_color
            
            # 存储记录
            if not hasattr(self, 'test_records'):
                self.test_records = []
            if self.show_word_info and not hasattr(self, 'last_recorded_index'):
                self.last_recorded_index = -1
            
            # 只有在新的单词结果显示时才添加记录
            if self.current_word_index != getattr(self, 'last_recorded_index', -1):
                # 添加完整记录（包括词性和释义）
                full_record = {
                    'word': record_text,
                    'status': status,
                    'pos': pos,
                    'meaning': meaning,
                    'color': record_color
                }
                self.test_records.append(full_record)
                self.last_recorded_index = self.current_word_index
                
                # 保持最近的10条记录
                if len(self.test_records) > 10:
                    self.test_records.pop(0)
        
        # 显示测试记录
        if hasattr(self, 'test_records'):
            y_offset = 270  # 起始y坐标
            
            for record in self.test_records:
                # 显示单词和状态
                word_line = f"{record['word']} [{record['status']}]"
                self.theme.draw_text(self.screen, word_line, 
                                   (rect.left + 10, y_offset), 
                                   color=record['color'], size=16)
                
                # 显示词性和释义（如果有）
                if record['pos'] or record['meaning']:
                    info_text = f"{record['pos']} {record['meaning']}".strip()
                    
                    # 创建一个矩形区域用于换行显示
                    info_rect = pygame.Rect(
                        rect.left + 20,  # 左边缩进
                        y_offset + 20,   # 在单词下方
                        rect.width - 40,  # 右边留出空间
                        60  # 预留足够的高度
                    )
                    
                    # 使用换行文本绘制
                    lines = self._wrap_text(info_text, info_rect.width, size=14)
                    for i, line in enumerate(lines):
                        self.theme.draw_text(self.screen, line,
                                           (info_rect.left, info_rect.top + i * 16),
                                           color=self.theme.text_color, size=14)
                    
                    # 根据实际行数调整下一条记录的位置
                    y_offset += 30 + len(lines) * 16
                else:
                    y_offset += 40  # 如果没有释义，使用较小的间距
                
                # 检查是否超出面板底部
                if y_offset > rect.bottom - 30:
                    break

    def _draw_wrapped_text(self, text: str, rect: pygame.Rect, size: int = 28) -> None:
        """绘制自动换行的文本"""
        words = text.split()
        lines = []
        current_line = []
        
        for word in words:
            test_line = ' '.join(current_line + [word])
            test_surface = self.theme.render_text(test_line, size=size)
            
            if test_surface.get_width() <= rect.width:
                current_line.append(word)
            else:
                if current_line:
                    lines.append(' '.join(current_line))
                current_line = [word]
        
        if current_line:
            lines.append(' '.join(current_line))
        
        for i, line in enumerate(lines):
            self.theme.draw_text(self.screen, line, 
                               (rect.centerx, rect.top + i * (size + 5)),
                               center=True, size=size)

    def _draw_error_message(self) -> None:
        """绘制错误信息"""
        text_surface = self.theme.render_text("无法加载练习单词，请检查词库", size=36)
        rect = text_surface.get_rect(center=self.screen.get_rect().center)
        self.screen.blit(text_surface, rect)
        
    def _show_import_dialog(self) -> None:
        """显示导入对话框"""
        import tkinter as tk
        from tkinter import filedialog
        
        root = tk.Tk()
        root.withdraw()  # 隐藏主窗口
        
        file_path = filedialog.askopenfilename(
            title="选择要导入的词库文件",
            filetypes=[("JSON文件", "*.json"), ("所有文件", "*.*")]
        )
        
        if file_path:
            bank_name = None  # 可以添加输入框让用户指定名称
            if self.word_bank.import_word_bank(file_path, bank_name):
                self.load_words()  # 重新加载词库
                
    def _show_export_dialog(self) -> None:
        """显示导出对话框"""
        import tkinter as tk
        from tkinter import filedialog
        
        root = tk.Tk()
        root.withdraw()
        
        file_path = filedialog.asksaveasfilename(
            title="选择导出位置",
            defaultextension=".json",
            filetypes=[("JSON文件", "*.json"), ("所有文件", "*.*")]
        )
        
        if file_path:
            self.word_bank.export_word_bank(self.word_bank.current_bank, file_path) 

    def _wrap_text(self, text: str, max_width: int, size: int = 14) -> list:
        """将文本按指定宽度换行
        
        Args:
            text: 要换行的文本
            max_width: 最大宽度
            size: 字体大小
            
        Returns:
            list: 换行后的文本行列表
        """
        words = text.split()
        lines = []
        current_line = []
        
        for word in words:
            # 测试添加当前单词后的宽度
            test_line = ' '.join(current_line + [word])
            test_surface = self.theme.render_text(test_line, size=size)
            
            if test_surface.get_width() <= max_width:
                current_line.append(word)
        else:
                if current_line:
                    lines.append(' '.join(current_line))
                current_line = [word]
        
        if current_line:
            lines.append(' '.join(current_line))
        
        return lines 